package com.bjb.vr.common.service;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.*;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.exception.CommonException;
import com.bjb.vr.common.mapper.*;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.ResCusDevGroupVo;
import com.bjb.vr.common.vo.UmsAccountVo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.power.common.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.*;

/**
* @author caihaibo
* @description 针对表【res_group(房间表)】的数据库操作Service实现
* @createDate 2022-03-22 10:49:59
*/
@Service
@Slf4j
public class OptCusDevGroupService extends ServiceImpl<ResGroupMapper, ResGroup>{

    @Autowired
    ResDeviceMapper resDeviceMapper;
    @Autowired
    ResGroupMapper resGroupMapper;
    @Autowired
    ResGroupRefMapper resGroupRefMapper;

    @Autowired
    OptProdBundleMapper optProdBundleMapper;
    @Autowired
    OptProdBundleDetailMapper optProdBundleDetailMapper;
    @Autowired
    OptProdBundleGroupMapper optProdBundleGroupMapper;

    @Autowired
    ResBundleMapper resBundleMapper;
    @Autowired
    ResBundleDetailMapper resBundleDetailMapper;

    @Autowired
    ResLocalResourceService resLocalResourceService;
    @Autowired
    ResBundleDetailService resBundleDetailService;

    //分组管理查询列表
    public List<ResCusDevGroupVo> queryCusConfigDevGroupList(OptCusDevGroupAo resGroupAo) {
        Assert.notNull(resGroupAo.getTenantId(),"租户id不能为空！");

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        MPJLambdaWrapper<ResCusDevGroupVo> mpjLambdaWrapper = new MPJLambdaWrapper();

        mpjLambdaWrapper
                .select(ResGroup::getId)
                .select(ResGroup::getGroupName)
                .select(ResGroup::getCapacity)
                .selectAs(ResBundle::getId,"bundleId")
                .select(ResBundle::getResBundleName)
                .selectCount(ResGroupRef::getId,"devCount")
                .leftJoin(ResBundle.class,ResBundle::getId,ResGroup::getBundleId)
//                .leftJoin(ResBundleDetail.class,ResBundleDetail::getResBundleId,ResGroup::getBundleId)
//                .leftJoin(ResContent.class,ResContent::getId,ResBundleDetail::getContentId)
                .leftJoin(ResGroupRef.class,ResGroupRef::getGroupId,ResGroup::getId);
         mpjLambdaWrapper.eq(ResGroup::getTenantId,resGroupAo.getTenantId());
         mpjLambdaWrapper.groupBy(ResGroup::getId);
        List<ResCusDevGroupVo> resGroupList = resGroupMapper.selectJoinList(ResCusDevGroupVo.class,mpjLambdaWrapper);

        if(resGroupList!=null && resGroupList.size()>0) {
            buildNeedInfo(resGroupList);
        }
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);

        return resGroupList;
    }

    private void buildNeedInfo(List<ResCusDevGroupVo> resGroupList) {
        resGroupList.forEach(resCusDevGroupVo -> {
            MPJLambdaWrapper<ResCusDevGroupVo> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectSum(ResContent::getContentSize,"bundleCapacity")
                    .leftJoin(ResContent.class,ResContent::getId,ResBundleDetail::getContentId);
            mpjLambdaWrapper.eq(ResBundleDetail::getResBundleId,resCusDevGroupVo.getBundleId());
            ResCusDevGroupVo resCusDevGroupVo1 = resBundleDetailMapper.selectJoinOne(ResCusDevGroupVo.class,mpjLambdaWrapper);
            if(resCusDevGroupVo1!=null) {
                resCusDevGroupVo.setBundleCapacity(resCusDevGroupVo1.getBundleCapacity());
            }
        });
    }


    //设备组组管理 添加接口
    public boolean addCusConfigDevGroup(OptCusDevGroupAo resGroupAo) {
        Assert.notNull(resGroupAo.getTenantId(),"请选择客户");

        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        umsAccountVo.setTempTenantId(resGroupAo.getTenantId());

        LambdaQueryWrapper<ResGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ResGroup::getTenantId,resGroupAo.getTenantId());
        int count = resGroupMapper.selectCount(queryWrapper);
        if(count>0){
            throw new CommonException("一个租户只能创建一个设备组，该租户已存在设备！");
        }

        ResGroup resGroup = new ResGroup();
        resGroup.setGroupName(resGroupAo.getGroupName());
        resGroup.setCapacity(resGroupAo.getCapacity());
        resGroup.setGroupCode(UUIDUtil.getUuid32());
        resGroup.setTenantId(resGroupAo.getTenantId());
        resGroup.setContentId((long) -1);
        resGroup.setSectionNo(-1);
        resGroup.setClassState(-1);
        resGroup.setSoundState(-1);
        resGroup.setLockState(-1);
        resGroup.setPlayState(-1);
        resGroup.setCtrlModeState(-1);
        resGroup.setTimeline(-1);
        resGroup.setState(1);
        resGroup.setBundleUpdateSwitch(1);
        resGroup.setGmtCreate(LocalDateTime.now());
        return this.save(resGroup);
    }


    public boolean editCusConfigDevGroup(OptCusDevGroupAo resGroupAo) {
        Assert.notNull(resGroupAo.getTenantId(),"请选择客户");
        Assert.notNull(resGroupAo.getId(),"设备组id不能为空");

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        ResGroup resGroup = new ResGroup();
        if(!"".equals(resGroupAo.getGroupName())&&resGroupAo.getGroupName()!=null){
            resGroup.setGroupName(resGroupAo.getGroupName());
        }
        if(resGroupAo.getBundleId()!=null){
            resGroup.setBundleId(resGroupAo.getBundleId());
        }
        if(resGroupAo.getCapacity()!=null){
            resGroup.setCapacity(resGroupAo.getCapacity());
        }
         resGroup.setId((long)resGroupAo.getId());
         resGroup.setGmtModified(LocalDateTime.now());

         boolean result = false;
         result = this.updateById(resGroup);

         ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
         return result;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean setCusConfigDevGroupBundle(OptCusDevGroupAo resGroupAo) {
        Assert.notNull(resGroupAo.getTenantId(),"请选择客户");
        Assert.notNull(resGroupAo.getId(),"设备组id不能为空");
        Assert.notNull(resGroupAo.getBundleId(),"资源包id不能为空");

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        ResGroup oldResGroup = this.getById(resGroupAo.getId());
        //未设置资源包
        if(oldResGroup.getBundleId() == null){
            if(resGroupAo.getBundleId()!=null){
                //绑定产品包
                bindResBundle(resGroupAo.getTenantId(),resGroupAo.getBundleId(),resGroupAo.getId());
                //本地表插入新资源包数据
                addLocalResourceByProdBundleId(resGroupAo.getTenantId(),resGroupAo.getBundleId());
            }
        }else{//修改资源包
            //本地表删除旧资源包数据
            deleteLocalResourceByBundleId(resGroupAo.getTenantId(),oldResGroup.getBundleId());
            //删除教师端资源包和绑定关系
            deleteLocalResBundleAndBind(resGroupAo.getTenantId(),oldResGroup.getBundleId(),resGroupAo.getId(),resGroupAo.getBundleId());
            //绑定产品包
            bindResBundle(resGroupAo.getTenantId(),resGroupAo.getBundleId(),resGroupAo.getId());
            //本地表插入新资源包数据
            addLocalResourceByProdBundleId(resGroupAo.getTenantId(),resGroupAo.getBundleId());
        }

        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return true;
    }

    /**
     * 删除教师端资源包和绑定关系
     * @param tenantId
     * @param bundleId
     * @param groupId
     */
    private void deleteLocalResBundleAndBind(String tenantId, Long bundleId, Long groupId) {

            //删除resBundle
            LambdaQueryWrapper<ResBundle> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(ResBundle::getTenantId,tenantId);
            lambdaQueryWrapper.eq(ResBundle::getId,bundleId);
            resBundleMapper.delete(lambdaQueryWrapper);
            //删除resBundleDetail
            LambdaQueryWrapper<ResBundleDetail> resBundleDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            resBundleDetailLambdaQueryWrapper.eq(ResBundleDetail::getTenantId,tenantId);
            resBundleDetailLambdaQueryWrapper.eq(ResBundleDetail::getResBundleId,bundleId);
            resBundleDetailMapper.delete(resBundleDetailLambdaQueryWrapper);
            //删除optProdBundleGroup
            LambdaQueryWrapper<OptProdBundleGroup> optProdBundleGroupLambdaQueryWrapper = new LambdaQueryWrapper<>();
            optProdBundleGroupLambdaQueryWrapper.eq(OptProdBundleGroup::getGroupId,groupId);
            optProdBundleGroupLambdaQueryWrapper.eq(OptProdBundleGroup::getResBundleId,bundleId);
            optProdBundleGroupMapper.delete(optProdBundleGroupLambdaQueryWrapper);
    }

    /**
     * 删除教师端资源包和绑定关系
     * @param tenantId
     * @param bundleId
     * @param groupId
     * @param proBundleId
     */
    private void deleteLocalResBundleAndBind(String tenantId, Long bundleId, Long groupId, Long proBundleId) {

        //删除resBundle
        LambdaQueryWrapper<ResBundle> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ResBundle::getTenantId,tenantId);
        lambdaQueryWrapper.eq(ResBundle::getId,bundleId);
        resBundleMapper.delete(lambdaQueryWrapper);
        //删除resBundleDetail
        LambdaQueryWrapper<ResBundleDetail> resBundleDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
        resBundleDetailLambdaQueryWrapper.eq(ResBundleDetail::getTenantId,tenantId);
        resBundleDetailLambdaQueryWrapper.eq(ResBundleDetail::getResBundleId,bundleId);
        resBundleDetailMapper.delete(resBundleDetailLambdaQueryWrapper);
        //删除optProdBundleGroup
        LambdaQueryWrapper<OptProdBundleGroup> optProdBundleGroupLambdaQueryWrapper = new LambdaQueryWrapper<>();
        optProdBundleGroupLambdaQueryWrapper.eq(OptProdBundleGroup::getGroupId,groupId);
        optProdBundleGroupLambdaQueryWrapper.eq(OptProdBundleGroup::getResBundleId,bundleId);
        optProdBundleGroupLambdaQueryWrapper.eq(OptProdBundleGroup::getProdBundleId,proBundleId);
        optProdBundleGroupMapper.delete(optProdBundleGroupLambdaQueryWrapper);
    }

    /**
     * 绑定产品包
     * @param tenantId
     * @param bundleId 产品包id
     * @param groupId
     */
    public void bindResBundle(String tenantId,Long bundleId,Long groupId){
        OptProdBundle optProdBundle = optProdBundleMapper.selectById(bundleId);
        //复制产品包
        ResBundle resBundle = new ResBundle();
        resBundle.setTenantId(tenantId);
        resBundle.setResBundleName(optProdBundle.getResBundleName());
        resBundle.setBundleType(optProdBundle.getBundleType());
        resBundle.setCapacity(optProdBundle.getCapacity());
        resBundleMapper.insert(resBundle);
        resBundleDetailService.copyResBundleDetailFromOptProd(tenantId,bundleId,resBundle.getId());

        //分组设置教师端资源包id
        ResGroup resGroup = new ResGroup();
        resGroup.setBundleId(resBundle.getId());
        resGroup.setId(groupId);
        resGroup.setGmtModified(LocalDateTime.now());
        resGroupMapper.updateById(resGroup);

        //设置教师端资源包产品包绑定关系
        OptProdBundleGroup optProdBundleGroup = new OptProdBundleGroup();
        optProdBundleGroup.setProdBundleId(bundleId);
        optProdBundleGroup.setGroupId(groupId);
        optProdBundleGroup.setResBundleId(resBundle.getId());
        optProdBundleGroupMapper.insert(optProdBundleGroup);
    }

    /**
     * 移除资源包绑定
     * @param tenantId
     * @param bundleId
     */
    public void removeBindResBundle(String tenantId,Long bundleId,Long groupId){
        ResBundle resBundle = new ResBundle();
        resBundle.setId(bundleId);
        resBundle.setTenantId("");
        resBundleMapper.updateById(resBundle);

        UpdateWrapper<ResBundleDetail> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("res_bundle_id",bundleId);
        ResBundleDetail resBundleDetail = new ResBundleDetail();
        resBundleDetail.setTenantId("");
        resBundleDetailMapper.update(resBundleDetail,updateWrapper);
    }

    /**
     * 删除本地资源表数据
     * @param tenantId
     * @param bundleId
     */
    public void deleteLocalResourceByBundleId(String tenantId,Long bundleId){
        resLocalResourceService.deleteLocalResourceByBundleId(tenantId,bundleId);
    }

    /**
     * 添加本地资源表数据
     * @param tenantId
     * @param bundleId
     */
    public void addLocalResourceByProdBundleId(String tenantId,Long bundleId){

        resLocalResourceService.addLocalResourceByProdBundleId(tenantId,bundleId);
    }

    public boolean removeCusConfigDevGroupBundle(OptCusDevGroupAo resGroupAo) {


        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);

        ResGroup resGroup = Optional.ofNullable(resGroupMapper.selectById(resGroupAo.getId())).orElseThrow(RuntimeException::new);
        LambdaUpdateWrapper<ResGroup> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ResGroup::getGmtModified,LocalDateTime.now());
        updateWrapper.set(ResGroup::getBundleId,null);
        updateWrapper.eq(ResGroup::getId,resGroupAo.getId());
        int count = resGroupMapper.update(resGroup,updateWrapper);
        //本地表删除资源包数据
        deleteLocalResourceByBundleId(resGroupAo.getTenantId(),resGroupAo.getBundleId());
        //移除资源包绑定
        deleteLocalResBundleAndBind(resGroupAo.getTenantId(),resGroupAo.getBundleId(),resGroupAo.getId());
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return count ==1;
    }

    public boolean removeGroupList(String ids) {
        String[] idArray = ids.split(",");
        Long[] intArray = Convert.toLongArray(idArray);
        return  removeByIds(Arrays.asList(intArray));
    }

    //分组管理-设备组查询列表
    public IPage<ResDevice> queryGroupDevList(OptCusDevGroupAo resGroupAo) {
        Assert.notNull(resGroupAo.getId(), "分组Id不能为空！");
        MPJLambdaWrapper<ResDevice> joinQueryWrapper = new MPJLambdaWrapper<>();
        joinQueryWrapper
                .select(ResDevice::getUdid)
                .select(ResDevice::getDevName)
                .select(ResDevice::getMode)
                .select(ResDevice::getTotalMem)
                .select(ResDevice::getDevModel)
                .innerJoin(ResGroupRef.class,ResGroupRef::getDevId,ResDevice::getId)
                .innerJoin(ResGroup.class,ResGroup::getId,ResGroupRef::getGroupId);
        joinQueryWrapper.eq(ResGroup::getId,resGroupAo.getId());
        return resDeviceMapper.selectPage(new Page<>(resGroupAo.getCurrent(), resGroupAo.getSize()), joinQueryWrapper);
    }


}




